package model.load
{
	import flash.display.Loader;
	import flash.events.Event;
	import flash.events.IOErrorEvent;
	import flash.events.ProgressEvent;
	import flash.events.TimerEvent;
	import flash.net.URLLoader;
	import flash.net.URLLoaderDataFormat;
	import flash.net.URLRequest;
	import flash.utils.ByteArray;
	
	import global.GameState;
	
	import model.system.TraceManager;
	
	import utils.EnterFrameTimer;

	public class RemoteLoader
	{
		private var urlLoader:URLLoader;
		private var loader:Loader;
		
		private var loadMessage:ILoadMessage;
		private var _isIdle:Boolean = true;
		private var timeoutTimer:EnterFrameTimer;
		
		public function RemoteLoader()
		{
			initLoader();
			initTimeOutTimer();
		}
		
		public function get isIdle():Boolean
		{
			return _isIdle;
		}

		private function initTimeOutTimer():void
		{
			timeoutTimer = new EnterFrameTimer(GameState.REMOTE_LOAD_TIMEROUT,1);
			timeoutTimer.addEventListener(TimerEvent.TIMER_COMPLETE,onTimeOut);
		}
		
		private function initLoader():void
		{
			urlLoader = new URLLoader();
			urlLoader.addEventListener(Event.COMPLETE,onLoadComplete);
			urlLoader.addEventListener(ProgressEvent.PROGRESS,onProgress);
			urlLoader.addEventListener(IOErrorEvent.IO_ERROR,onIOError);
			
			loader = new Loader();
			loader.contentLoaderInfo.addEventListener(Event.COMPLETE,onLoadBytesComplete);
			loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,onLoaderError);
		}
		
		private function onLoaderError(event:IOErrorEvent):void
		{
			TraceManager.getInstance().out("Loader Error:",loadMessage.url);
			clear();
		}
		
		private function onProgress(event:ProgressEvent):void
		{
			var total:Number = event.bytesTotal;
			var v:Number = event.bytesLoaded;
			
			if (loadMessage)
			{
				loadMessage.percent = v / total;
			}
		}
		
		private function onIOError(event:IOErrorEvent):void
		{
			TraceManager.getInstance().out("Load Error:",loadMessage.url);
			clear();
		}
		
		public function updateLoadMessage(loadMessage:ILoadMessage):void
		{
			this.loadMessage = loadMessage;
			_isIdle = false;
			urlLoader.dataFormat = loadMessage.dataFormat;
			timeoutTimer.delay = loadMessage.timeout;
			loadMessage.addEventListener(Event.CANCEL,onLoadCancel);
			startLoad();
		} 
		
		private function onLoadCancel(event:Event):void
		{
			TraceManager.getInstance().out("Load cancel:");
			clear();
			
		}
		
		private function startLoad():void
		{
			var urlRequest:URLRequest = new URLRequest(loadMessage.url);
			urlRequest.method = loadMessage.method;
			
			if (loadMessage.urlvariable)
			{
				urlRequest.data = loadMessage.urlvariable;
			}
			
			if (loadMessage.contentType)
			{
				urlRequest.contentType = loadMessage.contentType;
			}
			
			urlLoader.load(urlRequest);
			
			timeoutTimer.start();
			TraceManager.getInstance().out("Load Start:",loadMessage.url);
		}
		
		private function onLoadComplete(event:Event):void
		{
			if (loadMessage == null)
			{
				return;
			}
			
			TraceManager.getInstance().out("Load Complete:",loadMessage.url);
			if (loadMessage.dataFormat == URLLoaderDataFormat.BINARY && loadMessage.isDisplayObject == true)
			{
				var byteArray:ByteArray = ByteArray(urlLoader.data);
				if (loadMessage.isCompress)
				{
					byteArray.uncompress();
				}
				loader.loadBytes(byteArray);
			}
			else
			{
				loadMessage.back(urlLoader.data);
				clear();
				
			}
			
		}
		
		private function onLoadBytesComplete(event:Event):void
		{
			loadMessage.back(loader.content);
			clear();
		}
		
		private function onTimeOut(event:TimerEvent):void
		{
			if (loadMessage.isTimeOutReload)
			{
				loadMessage.send();
			}
			loadMessage.onTimeOut();
			TraceManager.getInstance().out("Load TimeOut:",loadMessage.url,loadMessage.isTimeOutReload);
			clear();
			
		}
		
		public function clear():void
		{
			loadMessage.removeEventListener(Event.CANCEL,onLoadCancel);
			
			
			urlLoader.close();
			urlLoader.data = null;
			_isIdle = true;
			loadMessage = null;
			timeoutTimer.reset();
		}
	}
}